package com.gitee.huanminabc.fastboot.load.stage.syncstage;

import com.gitee.huanminabc.jcommon.reflect.AnnotationUtil;
import com.gitee.huanminabc.jcommon.reflect.ClassUtil;
import com.gitee.huanminabc.fastboot.context.AppContext;
import com.gitee.huanminabc.fastboot.context.AppContextUtil;
import com.gitee.huanminabc.fastboot.load.hook.ClassLoadContainerFinishLifecycleHook;
import com.gitee.huanminabc.fastboot.load.classload.ClassLoadIntercept;
import com.gitee.huanminabc.fastboot.load.hook.LifecycleHook;
import lombok.extern.slf4j.Slf4j;

import java.lang.annotation.Annotation;
import java.util.Set;

/**
 * @description: 类转换为容器对象阶段
 * @author: huanmin
 * @create: 2025-04-01 10:56
 **/
@Slf4j
public class ClassLoadContainerStage implements AppLoadSyncStage {
    private static final ClassLoadContainerAopChildStage classLoadContainerAopChildStage = new ClassLoadContainerAopChildStage();
    @Override
    public void run() {
        try {
            //创建AOP代理对象
            if (AppContext.appBaseInfoConfig.getAop()) {
                classLoadContainerAopChildStage.createAopProxy();
            }
            Set<Class<?>> entries = AppContext.allClasses;
            entries.parallelStream().forEach(ClassLoadContainerStage::coreCreateBeanToContainer);
            componentSortLargeToSmall();
            log.debug("ClassLoadContainerStage: [{}]  load success", AppContext.containerNameAll.size());
            //执行类转对象完成的钩子
            new ClassLoadContainerFinishLifecycleHook().run();
        } catch (Exception e) {
            log.error("ClassLoadContainerStage load error", e);
            System.exit(1);
        } finally {
            classLoadContainerAopChildStage.clear();
        }
    }

    private static void coreCreateBeanToContainer(Class<?> clazz) {
        try {
            //如果是AOP注解的类单,不能通过普通的方式创建对象
            if (classLoadContainerAopChildStage.isAopClass(clazz)) {
                return;
            }
            //容器bean名称
            String beanName = getContainerBeanName(clazz);
            if (beanName != null) {
                //创建对象(半个-后续还需要注入实际的对象)
                Object newInstance = ClassUtil.newInstance(clazz);
                AppContextUtil.addAppContainer(beanName, newInstance);
                return;
            }
            //不管多少个拦截器,只会满足第一个
            for (ClassLoadIntercept classLoadIntercept : AppContext.classLoadIntercepts) {
                Object bean = classLoadIntercept.createBean(clazz);
                if (bean != null) {
                    //类是原始的类型. 但是对象可以是代理对象
                    AppContextUtil.addAppContainer(clazz, bean);
                    break;
                }
            }


        } catch (Exception e) {
            log.error("ClassLoadContainerStage: [{}]  load error", clazz.getName(), e);
            System.exit(1);
        }
    }

    //排序从大到小
    private static void componentSortLargeToSmall() {
        //监听器排序
        AppContext.appListenerMap.forEach((k, v) -> AppContextUtil.orderSort(v));

        //aop 排序
        AppContext.interceptorHandleMap.forEach((k, v) -> AppContextUtil.orderSort(v));
    }


    private static String getContainerBeanName(Class<?> clazz) {
        //判断是否是容器注,取第一个容器注解
        Annotation annotation = AnnotationUtil.getIncludeAnnotationFirst(AppContext.CONTAINER_ANNOTATION, clazz.getAnnotations());
        if (annotation != null) {
            if (ClassUtil.hasMoreThanOneConstructor(clazz)) {
                throw new RuntimeException("类:" + clazz.getName() + "有多个构造函数,只允许一个构造函数,要么无参构造函数,要么全参数的构造函数");
            }
            //获取注解的值,用于注入容器的,如果没有那么就是类名首字母小写
            return AppContextUtil.getBeanName(clazz);
        }
        return null;
    }


}
